package net.midnighttd.game.entity;

import net.midnighttd.engine.Engine;
import net.midnighttd.engine.entity.Entity;
import net.midnighttd.engine.view.sprite.*;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * Author: Adam Scarr
 * Date: 20/04/2009
 * Time: 3:51:11 PM
 */
public class Tower extends Entity implements MovementStateListener {
    private Sprite turret;
    private Unit target;
    private double range;
    private int damage;
    private double reload;
    private long cooldown;
    private long lastLoop;
    private String bulletSprite;
    private int bulletSpeed;
    private int cost;
    private boolean isUpgrade = false;
    private List<String> upgrades = new LinkedList<String>();

    public Tower(Tower tower) {
        super(tower);
        this.turret = tower.turret.copy();
        sprite.addChild(turret);
        range = tower.range;
        damage = tower.damage;
        reload = tower.reload;
        bulletSprite = tower.bulletSprite;
        bulletSpeed = tower.bulletSpeed;
        cost = tower.cost;
        upgrades = tower.upgrades;
        reload();
    }

    public Tower(Engine game, SpriteManager sm, Element element) {
        super(game, sm, element);

        turret = sm.getTemplateSprite(element.getAttribute("turretsprite"));
        sprite.addChild(turret);
        range = Double.valueOf(element.getAttribute("range"));
        damage = Integer.valueOf(element.getAttribute("damage"));
        reload = Double.valueOf(element.getAttribute("reload"));
        bulletSprite = element.getAttribute("bulletsprite");
        bulletSpeed = Integer.valueOf(element.getAttribute("bulletspeed"));
        cost = Integer.valueOf(element.getAttribute("cost"));

        NodeList upgradeList = element.getChildNodes();

        for(int i = 0; i < upgradeList.getLength(); i++) {
            Node upgrade = upgradeList.item(i);

            if(upgrade.getNodeName().equals("upgrade")) {
                upgrades.add(((Element)upgrade).getAttribute("name"));
            }
        }

        if(element.getNodeName().equals("upgrade")) {
            isUpgrade = true;
        }

        type = "tower";

        reload();
    }

    public void reload() {
        cooldown = (long)(reload * 1000000000l);
    }

    public void gameLogic() {
        long time = System.nanoTime();
        cooldown -= time - lastLoop;
        if(target != null && getDistanceTo(target) > range) {
            //System.out.println("Target left range.");
            target = null;
        }

        if(target != null && target.isDead()) {
            //System.out.println("Target died.");
            target = null;
        }

        if(target == null) {
            LinkedList<Entity> ents = engine.getEntityManager().getEntitiesByDistanceTo(this, range);
            Entity closest;

            closest = ents.poll();

            while(closest != null && !closest.getType().equals("unit")) {
                closest = ents.poll();
            }

            if(closest == null) {
                //System.out.println("No targets available.");
                target = null;
                return;
            } else {
                //System.out.println("Locked target " + closest.getName() + " at " + closest.getX() + ", " + closest.getY());
                target = (Unit)closest;
            }
        }

        turret.rotateToFace(target.getSprite());

        if(cooldown < 0) {
            reload();
            Sprite bullet = engine.getSpriteManager().getSprite(bulletSprite);
            bullet.addMovementStateListener(this);
            bullet.setLocation(getSprite().getCenterX() - bullet.getWidth() / 2, getSprite().getCenterY() - bullet.getHeight() / 2);
            bullet.moveTo(target.getSprite().getCenterX() - bullet.getWidth() / 2, target.getSprite().getCenterY() - bullet.getHeight() / 2, bulletSpeed);
            bullet.rotateToFace(target.getSprite());
        }

        lastLoop = time;
    }
    
    public void drawEntity(Graphics g) {
        turret.draw(g);
    }

    public void setLocation(int x, int y) {
        super.setLocation(x, y);
    }

    public Entity getDuplicate() {
        return new Tower(this);
    }

    public boolean isPassable() {
        return false;
    }

    /**
     * Clean up our bullets when they stop moving.
     */
    public void movementStateChanged(Sprite sprite, MovementState state, Movement movement) {
        if(state == MovementState.end) {
            engine.getSpriteManager().remove(sprite);
            if(target != null) {
                target.takesDamage(damage);
            }
        }
    }

    public int getDamage() {
        return damage;
    }

    public double getSpeed() {
        return reload;
    }

    public double getRange() {
        return range;
    }

    public int getCost() {
        return cost;
    }

    public boolean isUpgrade() {
        return isUpgrade;
    }

    public List<String> getUpgrades() {
        return upgrades;
    }

    public int getUpgradeCost(String upgradeName) {
        return ((Tower)engine.getEntityManager().getEntity(upgradeName)).getCost();
    }
}
